# 文件路径: src/data_access/base_repository.py

from abc import ABC, abstractmethod
from datetime import datetime
from typing import List
import pandas as pd

from src.enums.timeframe import Timeframe


class BaseRepository(ABC):
    """
    数据仓储的抽象基类 (Abstract Base Class)。
    定义了与数据源交互所需的所有方法的接口。
    """

    @abstractmethod
    def get_klines(
            self,
            symbol: str,
            timeframe: Timeframe,
            start_date: datetime,
            end_date: datetime
    ) -> pd.DataFrame:
        """
        根据指定的交易对、时间周期和日期范围，获取 K 线数据。

        Args:
            symbol: 交易对, 例如 'BTC/USDT'。
            timeframe: 时间周期, 例如 '1h', '1d'。
            start_date: 开始时间 (包含)。
            end_date: 结束时间 (不包含)。

        Returns:
            一个包含 K 线数据的 Pandas DataFrame，以时间为索引。
        """
        pass

    @abstractmethod
    def get_all_symbols(self) -> List[str]:
        """
        获取数据库中存储的所有唯一交易对。

        Returns:
            一个包含所有 symbol 字符串的列表。
        """
        pass

    @abstractmethod
    def save_klines(self, klines_df: pd.DataFrame):
        """
        将 K 线数据的 DataFrame 保存到数据库中。
        该方法应处理重复数据的插入问题（例如，通过唯一索引或 upsert 逻辑）。

        Args:
            klines_df: 包含待保存 K 线数据的 DataFrame。
                       必须包含 'time', 'symbol', 'timeframe' 等列。
        """
        pass

    @abstractmethod
    def get_kline_timestamps(
        self,
        symbol: str,
        timeframe: str,
        start_date: datetime,
        end_date: datetime
    ) -> pd.DatetimeIndex:
        """
        高效地只获取 K 线数据的时间戳索引。

        Args:
            symbol: 交易对。
            timeframe: 时间周期 (字符串形式, e.g., '1h')。
            start_date: 开始时间。
            end_date: 结束时间。

        Returns:
            一个 Pandas DatetimeIndex，包含了所有实际存在的时间戳。
        """
        pass
    # 你可以在这里添加更多数据访问方法的抽象定义，例如：
    # @abstractmethod
    # def get_factor_data(...) -> pd.DataFrame:
    #     pass
    #
    # @abstractmethod
    # def save_factor_data(...):
    #     pass
